/*
* Author: Chris Seguin
*
* This software has been developed under the copyleft
* rules of the GNU General Public License. Please
* consult the GNU General Public License for more
* details about use and distribution of this software.
*/
package org.acm.seguin.uml;
import java.awt.Dimension;
import java.awt.Point;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Iterator;
import java.util.StringTokenizer;
import org.acm.seguin.awt.ExceptionPrinter;
import org.acm.seguin.ide.common.SummaryLoaderThread;
import org.acm.seguin.summary.FileSummary;
import org.acm.seguin.summary.PackageSummary;
import org.acm.seguin.summary.TypeDeclSummary;
import org.acm.seguin.summary.TypeSummary;
import org.acm.seguin.summary.query.GetTypeSummary;
import org.acm.seguin.uml.line.AssociationRelationship;
import org.acm.seguin.uml.line.ImplementsRelationship;
import org.acm.seguin.uml.line.InheretenceRelationship;
import org.acm.seguin.uml.line.SegmentedLine;
/**
* Loads a UMLPackage panel from a package summary
*
*@author Chris Seguin
*/
class PackageLoader extends Thread {
private UMLPackage packagePanel;
private int defaultX;
private int defaultY;
private boolean loaded;
private String filename;
private PackageSummary loadSummary;
private File loadFile;
private InputStream loadStream;
/**
* Constructor for the PackageLoader object
*
*@param panel the panel that we are loading
*/
public PackageLoader(UMLPackage panel) {
packagePanel = panel;
defaultX = 20;
defaultY = 20;
loaded = false;
}
/**
* Main processing method for the PackageLoader object
*/
public void run() {
/*
* Don't run this until we have completed loading the
* summaries from disk
*/
SummaryLoaderThread.waitForLoading();
synchronized (PackageLoader.class) {
packagePanel.setLoading(true);
packagePanel.clear();
if (loadSummary != null) {
load(loadSummary);
}
if (loadFile != null) {
load(loadFile);
}
if (loadStream != null) {
load(loadStream);
}
packagePanel.updateClassListPanel();
packagePanel.setLoading(false);
packagePanel.repaint();
}
}
/**
* Description of the Method
*
*@param summary Description of Parameter
*/
public void start(PackageSummary summary) {
loadSummary = summary;
loadStream = null;
loadFile = null;
super.start();
}
/**
* Description of the Method
*
*@param filename Description of Parameter
*/
public void start(String filename) {
loadSummary = null;
loadStream = null;
loadFile = new File(filename);
super.start();
}
/**
* Description of the Method
*
*@param input Description of Parameter
*/
public void start(InputStream input) {
loadSummary = null;
loadStream = input;
loadFile = null;
super.start();
}
/**
* Gets the File attribute of the PackageLoader object
*
*@return The File value
*/
File getFile() {
PackageSummary summary = packagePanel.getSummary();
File dir = summary.getDirectory();
File inputFile;
if (dir == null) {
dir = new File(System.getProperty("user.home") +
File.separator + ".Refactory" +
File.separator + "UML");
dir.mkdirs();
inputFile = new File(dir, summary.getName() + ".uml");
}
else {
inputFile = new File(summary.getDirectory(), "package.uml");
}
return inputFile;
}
/**
* Returns the UMLType panel associated with a summary or null if none is
* available
*
*@param summary the type declaration
*@return the panel associated with the type
*/
private UMLType getUMLType(TypeDeclSummary summary) {
if (summary != null) {
TypeSummary typeSummary = GetTypeSummary.query(summary);
if (typeSummary != null) {
UMLType typePanel = packagePanel.findType(typeSummary);
if (typePanel == null) {
typePanel = addType(typeSummary, true);
}
return typePanel;
}
}
return null;
}
/**
* Returns the location of this class
*
*@param umlType the type panel
*@param summary the type summary
*@return the point where this type panel should be located
*/
private Point getLocation(UMLType umlType, TypeSummary summary) {
Dimension dim = umlType.getPreferredSize();
Point result = new Point(defaultX, defaultY);
defaultX += (20 + dim.width);
return result;
}
/**
* Reload the summaries
*
*@param summary the package summary
*/
private void load(PackageSummary summary) {
if (summary != null) {
defaultPositions(summary);
}
loadPositions(getFile());
}
/**
* Reload the summaries
*
*@param file Description of Parameter
*/
private void load(File file) {
loadPositions(file);
}
/**
* Reload the summaries
*
*@param input Description of Parameter
*/
private void load(InputStream input) {
loadPositions(input);
}
/**
* Loads all the classes into their default positions
*
*@param summary the package that is being loaded
*/
private void defaultPositions(PackageSummary summary) {
// Add all the types
Iterator iter = summary.getFileSummaries();
if (iter != null) {
while (iter.hasNext()) {
addFile((FileSummary) iter.next());
}
}
loadInheretence();
loadImplements();
loaded = true;
}
/**
* Adds all the types in a file
*
*@param fileSummary the file summary
*/
private void addFile(FileSummary fileSummary) {
Iterator iter = fileSummary.getTypes();
if (iter != null) {
while (iter.hasNext()) {
addType((TypeSummary) iter.next(), false);
}
}
}
/**
* Adds a UML type
*
*@param typeSummary the type summary being added
*@param foreign whether this type is in this package (true means it is
* from a different package
*@return The panel
*/
private UMLType addType(TypeSummary typeSummary, boolean foreign) {
UMLType umlType = new UMLType(packagePanel, typeSummary, foreign);
packagePanel.add(umlType);
umlType.setLocation(getLocation(umlType, typeSummary));
return umlType;
}
/**
* Loads the inheritence relationships
*/
private void loadInheretence() {
UMLType[] typeList = packagePanel.getTypes();
for (int ndx = 0; ndx < typeList.length; ndx++) {
TypeSummary current = typeList[ndx].getSummary();
TypeDeclSummary parent = current.getParentClass();
UMLType typePanel = getUMLType(parent);
if (typePanel != null) {
packagePanel.add(new InheretenceRelationship(typeList[ndx], typePanel));
}
}
}
/**
* Loads the inheritence relationships
*/
private void loadImplements() {
UMLType[] typeList = packagePanel.getTypes();
for (int ndx = 0; ndx < typeList.length; ndx++) {
if (typeList[ndx].isForeign()) {
continue;
}
TypeSummary current = typeList[ndx].getSummary();
Iterator iter = current.getImplementedInterfaces();
if (iter != null) {
while (iter.hasNext()) {
TypeDeclSummary next = (TypeDeclSummary) iter.next();
UMLType typePanel = getUMLType(next);
if (typePanel != null) {
SegmentedLine nextLine;
if (current.isInterface()) {
nextLine = new InheretenceRelationship(typeList[ndx], typePanel);
}
else {
nextLine = new ImplementsRelationship(typeList[ndx], typePanel);
}
packagePanel.add(nextLine);
}
}
}
}
}
/**
* Loads the package from disk
*
*@param inputFile Description of Parameter
*/
private void loadPositions(File inputFile) {
try {
FileReader fr = new FileReader(inputFile);
BufferedReader input = new BufferedReader(fr);
loadPositions(input);
}
catch (FileNotFoundException fnfe) {
// This is a normal and expected condition
}
catch (IOException ioe) {
ExceptionPrinter.print(ioe);
}
}
/**
* Loads the package from disk
*
*@param inputStream Description of Parameter
*/
private void loadPositions(InputStream inputStream) {
try {
InputStreamReader fr = new InputStreamReader(inputStream);
BufferedReader input = new BufferedReader(fr);
loadPositions(input);
input.close();
fr.close();
}
catch (IOException ioe) {
ExceptionPrinter.print(ioe);
}
}
/**
* Loads the package from disk
*
*@param input Description of Parameter
*@exception IOException Description of Exception
*/
private void loadPositions(BufferedReader input) throws IOException {
String line = input.readLine();
while (line != null) {
// Decide what to do
char ch = line.charAt(0);
if (ch == 'P') {
positionPanel(line);
}
else if (ch == 'S') {
positionLine(line);
}
else if (ch == 'A') {
positionAttribute(line);
}
else if (ch == 'V') {
loadVersion(line);
}
// Read the next line
line = input.readLine();
}
}
/**
* position the type in the UMLPackage
*
*@param buffer the line that describes where to position the type
*/
private void positionPanel(String buffer) {
StringTokenizer tok = new StringTokenizer(buffer, "[]{},\n");
String code = tok.nextToken();
String id = tok.nextToken();
String x = tok.nextToken();
String y = tok.nextToken();
UMLType type = packagePanel.find(id);
if (type == null) {
return;
}
Point pt = type.getLocation();
int nX = pt.x;
int nY = pt.y;
try {
nX = Integer.parseInt(x);
nY = Integer.parseInt(y);
}
catch (NumberFormatException nfe) {
}
type.setLocation(nX, nY);
}
/**
* Position the line
*
*@param buffer the line read from the file
*/
private void positionLine(String buffer) {
StringTokenizer tok = new StringTokenizer(buffer, "[]{}\n");
String code = tok.nextToken();
String pair = tok.nextToken();
String position = tok.nextToken();
tok = new StringTokenizer(pair, ",");
String first = tok.nextToken();
String second = tok.nextToken();
SegmentedLine line = packagePanel.find(first, second);
if (line != null) {
line.load(position);
}
}
/**
* The attribute
*
*@param buffer the input string
*/
private void positionAttribute(String buffer) {
StringTokenizer tok = new StringTokenizer(buffer, "[]{}\n");
String code = tok.nextToken();
String pair = tok.nextToken();
String position = tok.nextToken();
String fieldPosition = tok.nextToken();
tok = new StringTokenizer(pair, ",");
String first = tok.nextToken();
String second = tok.nextToken();
UMLType type = packagePanel.find(first);
if (type == null) {
return;
}
UMLField field = type.getField(second);
if (field == null) {
return;
}
field.setAssociation(true);
AssociationRelationship ar = type.convertToAssociation(packagePanel, field);
ar.load(position);
// Set the field label position
tok = new StringTokenizer(fieldPosition, ",");
String x = tok.nextToken();
String y = tok.nextToken();
try {
field.setLocation(Integer.parseInt(x), Integer.parseInt(y));
}
catch (NumberFormatException nfe) {
}
}
/**
* Loads a version line
*
*@param buffer the input line that contains the version number and package
* name
*/
private void loadVersion(String buffer) {
StringTokenizer tok = new StringTokenizer(buffer, "[]:\n");
String key = tok.nextToken();
String versionID = tok.nextToken();
String packageName = "";
if (tok.hasMoreTokens()) {
packageName = tok.nextToken();
}
System.out.println("Loading: " + packageName + " from a file with version " + versionID);
if (!loaded) {
PackageSummary summary = PackageSummary.getPackageSummary(packageName);
packagePanel.setSummary(summary);
defaultPositions(summary);
}
}
}